package com.chensi.socket;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

import com.chensi.common.Constants;
import com.chensi.common.Global;
import com.chensi.util.ConvertUtil;

/**
 * Socket处理器
 * @author chensi
 * @version 2016-8-20 下午4:12:44
 */
@Component
public class MyWebSocketHandler implements WebSocketHandler {

	private static final Logger logger = LoggerFactory.getLogger(MyWebSocketHandler.class);

	/**
	 * 建立连接后，session托管给全局map容器管理
	 */
	@Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception {
		Integer uid = (Integer) session.getAttributes().get(Constants.SOCKET_USER);
		if (Global.userSocketSessionMap.get(uid) == null) {
			Global.userSocketSessionMap.put(uid, session);
			//TODO 群发在线人员好友更新请求
			logger.info("当前WebSocketSession数量为[{}]", Global.userSocketSessionMap.size());
		}
	}

	/**
	 * 消息处理，在客户端通过Websocket API发送的消息会经过这里，然后进行相应的处理
	 */
	@Override
	public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
		if (message.getPayloadLength() == 0) {
			return;
		}
		//解析socket报文
		MessageSend send = Global.gson.fromJson(message.getPayload().toString(), MessageSend.class);
		To to=send.getTo();
		Mine mine=send.getMine();
		//封装为接收信息
		MessageReceive receive=new MessageReceive();
		receive.setEmit(send.getType());
		Msg data=new Msg();
		data.setId(mine.getId());
		data.setAvatar(mine.getAvatar());
		data.setContent(mine.getContent());
		data.setType(to.getType());
		data.setUsername(mine.getUsername());
		receive.setData(data);
		sendMessageToUser(ConvertUtil.StringToInteger(send.getTo().getId()), new TextMessage(Global.gson.toJson(receive)));
	}

	/**
	 * 消息传输错误处理
	 */
	@Override
	public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
		if (session.isOpen()) {
			session.close();
		}
		Iterator<Entry<Integer, WebSocketSession>> it = Global.userSocketSessionMap.entrySet().iterator();
		// 移除Socket会话
		while (it.hasNext()) {
			Entry<Integer, WebSocketSession> entry = it.next();
			if (entry.getValue().getId().equals(session.getId())) {
				Global.userSocketSessionMap.remove(entry.getKey());
				//TODO 群发在线人员好友更新请求
				logger.info("会话出错，已经移除:用户ID:" + entry.getKey());
				logger.info("当前WebSocketSession数量为[{}]", Global.userSocketSessionMap.size());
				break;
			}
		}
	}

	/**
	 * 关闭连接后
	 */
	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
		logger.info("Websocket:" + session.getId() + "已经关闭");
		Iterator<Entry<Integer, WebSocketSession>> it = Global.userSocketSessionMap.entrySet().iterator();
		// 移除Socket会话
		while (it.hasNext()) {
			Entry<Integer, WebSocketSession> entry = it.next();
			if (entry.getValue().getId().equals(session.getId())) {
				Global.userSocketSessionMap.remove(entry.getKey());
				//TODO 群发在线人员好友更新请求
				logger.info("Socket会话已经移除:用户ID:" + entry.getKey());
				logger.info("当前WebSocketSession数量为[{}]", Global.userSocketSessionMap.size());
				break;
			}
		}
	}

	@Override
	public boolean supportsPartialMessages() {
		return false;
	}

	/**
	 * 给所有在线用户发送消息
	 * @param message
	 * @throws IOException
	 */
	public void broadcast(final TextMessage message) throws IOException {
		Iterator<Entry<Integer, WebSocketSession>> it = Global.userSocketSessionMap.entrySet().iterator();
		// 多线程群发
		while (it.hasNext()) {
			final Entry<Integer, WebSocketSession> entry = it.next();
			if (entry.getValue().isOpen()) {
				// entry.getValue().sendMessage(message);
				new Thread(new Runnable() {
					public void run() {
						try {
							if (entry.getValue().isOpen()) {
								entry.getValue().sendMessage(message);
							}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}).start();
			}
		}
	}

	/**
	 * 给某个用户发送消息
	 * 
	 * @param userName
	 * @param message
	 * @throws IOException
	 */
	public void sendMessageToUser(Integer uid, TextMessage message) throws IOException {
		WebSocketSession session = Global.userSocketSessionMap.get(uid);
		if (session != null && session.isOpen()) {
			session.sendMessage(message);
		}
	}

}
